/*--------------------------------------------------------------
 * File: devMA8.c 编码类型：C语言  UTF-8
 * Author WRS (1352509846@qq.com)
 * 功能: 模拟的设备2(MA8)功能
 * Version 0.1
 * Date 2024-10-15 
 * 
 * @copyright Copyright (c) 2024
 * 
----------------------------------------------------------------*/
#include "devMA8.h"
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "data.h"
#include "ui.h"
#include "Dev_task.h"

extern lv_indev_t * indev_keypad;
extern lv_group_t * group_MA8;
extern const Env_ST Env_st;

// static const char *TAG = "devMA8 ";
char devMA8_Name[20] = {"MA8: 0"};
ma8_t ma8_info = {0};

TaskHandle_t devMA8_task_Handle = NULL;

/*--------------------------------------------------------------
 * 功能: 初始化ma8_info
 * 
----------------------------------------------------------------*/
void ma8_info_Init(void)
{
    NVS_data_read_blob(DEV_INFO_NAMESPACE, MA8_key, (uint8_t *)&ma8_info, sizeof(ma8_t));
    if(ma8_info.dev_flag == Info_Save)
    {
        ma8_info.devType = emTypeMA8;
        ma8_info.dev_index = 0;
        ma8_info.dev_SCRindex = 0;
        ma8_info.devAddrNow = 0x00;
        // 清零 dev_AI 数组
        memset(ma8_info.dev_AI, 0, sizeof(ma8_info.dev_AI));
        // 清零 dev_AO 数组
        memset(ma8_info.dev_AO, 0, sizeof(ma8_info.dev_AO));
        return ;
    }
    ma8_info.devType = emTypeMA8;
    ma8_info.devLEDtime = emFlashRequest;
    ma8_info.dev_num = 1;
    ma8_info.dev_index = 0;
    ma8_info.dev_SCRindex = 0;
    ma8_info.devAddrNow = 0x00;
    ma8_info.dev_state = devStart;
}

/*--------------------------------------------------------------
 * 功能: 模拟的设备1初始化
 * 
----------------------------------------------------------------*/
static esp_err_t devMA8_init(void)
{
    ui_Scr6_MA8_screen_init();
    _ui_screen_change(&ui_Scr6_MA8, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, NULL);
    lv_indev_set_group(indev_keypad, group_MA8);
    lv_group_focus_obj(ui_MA8_DpDown1);   // 默认聚焦到下拉框上
    
    return ESP_OK;
}


/*--------------------------------------------------------------
 * 功能: 模拟设备1启动
 * 
----------------------------------------------------------------*/
void devMA8_Start(void)
{
    devMA8_init();
}

/*--------------------------------------------------------------
 * 功能: 模拟设备2停止
 * 
----------------------------------------------------------------*/
void devMA8_Stop(void)
{
    if(ui_Del_Scr_timer != NULL)
    {
        lv_timer_del(ui_Del_Scr_timer);
        ui_Del_Scr_timer = NULL;
    }
    if(Led_timer != NULL)
    {
        lv_timer_del(Led_timer);
        G_LED_SET(LED_OFF);
        Led_timer = NULL;
    }
    if(ui_Scr6_MA8_timer != NULL)
    {
        lv_timer_del(ui_Scr6_MA8_timer);
        ui_Scr6_MA8_timer = NULL;
    }
    if(ui_Scr6_MA8 != NULL)
    {
        lv_obj_del(ui_Scr6_MA8);
        ui_Scr6_MA8 = NULL;
    }    
    memset(ma8_info.dev_AOlast, 0, sizeof(ma8_info.dev_AOlast));
    memset(ma8_info.dev_AIlast, 0, sizeof(ma8_info.dev_AIlast));
}

/*--------------------------------------------------------------
 * 功能: 设定AO输出值
 * DAC芯片是10bit的 所以1024对应2.5V，所以819.2对应2V
 * 参数: BM42ch 
 * 参数: val 
 * 适用2.5V的参考，设定820=2V，放大5倍后为10V
----------------------------------------------------------------*/
static void SPI_DAC_Output_MA8(uint8_t devIndex, uint16_t BM42ch, uint16_t val)
{
    uint8_t ch = BM42ch - MA8_AO_CH0;

    if(devIndex > MA8_MAX_NUM)
    {
        MY_ERROR("MA8 dev Index ERROR: %d", devIndex);
    }
    if(ch >= MA8_AOChannel)
    {
        MY_ERROR("MA8 AOch ERROR: %d", ch);
    }
    ma8_info.dev_AO[devIndex][ch] = val & 0x03ff; //0~820 ---->0~2V---->0~20mA
}

static uint32_t Get_ADCReturnValue_MA8(uint8_t devIndex, uint8_t ML12ch, uint8_t Type)
{
    uint32_t u_data = 0;

    switch (ma8_info.dev_Random_mode[devIndex])
    {
        case emRandom_0:
            u_data = 0;
            break;
        case emRandom_2:
            u_data = 656;
            break;
        case emRandom_10:
            u_data = 3276;
            break;
        case emRandom_0_10:
            u_data = Random_data_in_range(0, 3276);
            break;
        case emRandom_2_10:
            u_data = Random_data_in_range(656, 3276); 
            break;
        case emRandom_Linear:
            u_data = Linear_data_in_range(0, 3276, 30); 
            break; 
        // case emRandom_sin:
        //     u_data = Random_data_in_sin(10, 50, 0);    // 振幅10，周期50Hz，相位偏移0
        //     break;
        case emRandom_SD:
            u_data = Random_data_in_sin(10, 50, 0);    // 振幅10，周期50Hz，相位偏移0
            break;            
        default:
            break;
    }

    return u_data;
}

/****************************************************************
 **描  述: 写入AO  DO信息
*****************************************************************/
void VARTable_RecVar_MA8(uint32_t ctrl, uint8_t *pValue, void *pVarDes)
{
    struct RS485_VarCtrl_ST *pRS485_VarCtrl_st = (struct RS485_VarCtrl_ST *)&ctrl;
    struct LocalVarDescription_ST *pLocalVarDescription_st = (struct LocalVarDescription_ST *)pVarDes;
    struct RS485_VarName_ST *pRS485_VarName_st = (struct RS485_VarName_ST *)&pLocalVarDescription_st->var_name;
    // struct RS485_VarName_ST *pRS485_VarName_st_tmp;
    uint32_t u32_data;
    int i;
    printf("VarName=%X,%X,%X,COM=%d\n", pRS485_VarName_st->VarName, pLocalVarDescription_st->var_length, pLocalVarDescription_st->VType_un.VarType, pRS485_VarCtrl_st->COMx);

    // 485协议
    if (Env_st.COMSet_st[pRS485_VarCtrl_st->COMx].protocol == em485)
    {
        // 写
        if (pRS485_VarCtrl_st->RWctrl == emRS485Write)
        {
            if (pRS485_VarName_st->VarName >= MA8_AO_CH0 && pRS485_VarName_st->VarName < MA8_AO_END)
            {
                u32_data = *(uint32_t *)pValue;
                printf("AO[%X]=%ld\n", pRS485_VarName_st->VarName - MA8_AO_CH0, u32_data);
                if(u32_data>1023)
                {
                    u32_data = 1023;
                }
                SPI_DAC_Output_MA8(ma8_info.dev_Addrindex, pRS485_VarName_st->VarName, u32_data);
            }
            else if (pRS485_VarName_st->VarName == emVarAOAll)
            {
                // 所有AO
                u32_data = *(uint32_t *)pValue;
                if(u32_data>1023)
                {
                    u32_data = 1023;
                }
                printf("AO[%d]=%ld\n", pRS485_VarName_st->VarName - MA8_AO_CH0, u32_data);
                for (i = 0; i < MA8_AOChannel; i++)
                {
                    SPI_DAC_Output_MA8(ma8_info.dev_Addrindex, MA8_AO_CH0 + i, u32_data);
                }
            }         
        }
    }
}

uint32_t VARTable_RecVarR_MA8(uint32_t ctrl, uint8_t *pValue, void *pVarDes, uint8_t *devaddr)
{
    struct RS485_VarCtrl_ST *pRS485_VarCtrl_st = (struct RS485_VarCtrl_ST *)&ctrl;
    struct LocalVarDescription_ST *pLocalVarDescription_st = (struct LocalVarDescription_ST *)pVarDes;
    struct RS485_VarName_ST *pRS485_VarName_st = (struct RS485_VarName_ST *)&pLocalVarDescription_st->var_name;
    uint32_t u32_data = 0;
    // uint8_t VarData[128];
    int i;

    MY_DEBUG("VarName=%X,%X,%X,COM=%d\n", pRS485_VarName_st->VarName, pLocalVarDescription_st->var_length, pLocalVarDescription_st->VType_un.VarType, pRS485_VarCtrl_st->COMx);

    if (Env_st.COMSet_st[pRS485_VarCtrl_st->COMx].protocol != em485)
        return 0;
    
    *devaddr = ma8_info.devAddr[ma8_info.dev_Addrindex];

    // 485协议
    if (pRS485_VarName_st->VarName >= MA8_AI_CH0 && pRS485_VarName_st->VarName < MA8_AI_END)
    {
        // 读取AI
        MY_DEBUG("read AI %X ", pRS485_VarName_st->VarName);        
        ma8_info.dev_AI[ma8_info.dev_Addrindex][pRS485_VarName_st->VarName-MA8_AI_CH0] = Get_ADCReturnValue_MA8(ma8_info.dev_Addrindex, pRS485_VarName_st->VarName-MA8_AI_CH0,0);
        memcpy(pValue, &ma8_info.dev_AI[ma8_info.dev_Addrindex][pRS485_VarName_st->VarName-MA8_AI_CH0], 4);
        return 4;
    }
    else if (pRS485_VarName_st->VarName >= MA8_AO_CH0 && pRS485_VarName_st->VarName < MA8_AO_END)
    {
        // 读取单路AO
        // 读取AO设定值，并不一定是真实值
        u32_data = ma8_info.dev_AO[ma8_info.dev_Addrindex][pRS485_VarName_st->VarName - MA8_AO_CH0];
        MY_DEBUG("read AO %lu ", u32_data);
    }
    else if (pRS485_VarName_st->VarName == emVarAOAll)
    {
        // 读取所有AO，0x20
        // 读取AO设定值，并不一定是真实值
        for (i = 0; i < MA8_AOChannel; i++)
        {
            u32_data = ma8_info.dev_AO[ma8_info.dev_Addrindex][i];
            memcpy(pValue, &u32_data, 4);
            MY_DEBUG("read AO %u ", *pValue);
            pValue += 4;
        }
        return MA8_AOChannel * 4;
    }
    else if (pRS485_VarName_st->VarName == emVarAIAll)
    {
        // 读取所有的AI
        for (i = 0; i < MA8_AIChannel; i++)
        {
            ma8_info.dev_AI[ma8_info.dev_Addrindex][i] = Get_ADCReturnValue_MA8(ma8_info.dev_Addrindex, i + MA8_AI_CH0, 0);
            memcpy(pValue, &ma8_info.dev_AI[ma8_info.dev_Addrindex][i], 4);
            pValue += 4;
        }
        return MA8_AIChannel * 4;
    } 
    else
    {
        return 0;
    }
    memcpy(pValue, &u32_data, 4);
    return 4;
}







